#pragma once

#include "base_view_model.h"
#include "application/map/lift/lift_manager.h"
#include "application/map/area/area_manager.h"
#include "application/map/caller/caller_manager.h"
#include "application/map/third_area/third_area_manager.h"
#include "application/map/auto_door/auto_door_manager.h"
#include "application/map/map_application_service.h"
#include <QAbstractListModel>
#include <QDateTime>
#include <QSet>
#include <QString>
#include <QTimer>
#include <memory>

namespace presentation {
namespace viewmodels {

// 电梯列表项
class LiftListItem {
    Q_GADGET
    Q_PROPERTY(int liftNum MEMBER m_liftNum)
    Q_PROPERTY(QString status MEMBER m_status)
    Q_PROPERTY(int currentFloor MEMBER m_currentFloor)
    Q_PROPERTY(bool isLocked MEMBER m_isLocked)
    Q_PROPERTY(bool isOnline MEMBER m_isOnline)
    Q_PROPERTY(QString liftType MEMBER m_liftType)

public:
    int m_liftNum{0};
    QString m_status;
    int m_currentFloor{1};
    bool m_isLocked{false};
    bool m_isOnline{false};
    QString m_liftType;
};

// 电梯列表模型
class LiftListModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum LiftRoles {
        LiftNumRole = Qt::UserRole + 1,
        StatusRole,
        CurrentFloorRole,
        IsLockedRole,
        IsOnlineRole,
        LiftTypeRole,
        AvailableFloorsRole
    };
    Q_ENUM(LiftRoles)

    explicit LiftListModel(QObject* parent = nullptr);
    ~LiftListModel() override = default;

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

    Q_INVOKABLE QVariantMap getLiftData(int row) const;
    Q_INVOKABLE QVariantList getAvailableFloors(int liftNum) const;

    void updateData(const QList<std::shared_ptr<application::lift::BaseLift>>& lifts);

private:
    struct LiftData {
        int liftNum;
        QString status;
        int currentFloor;
        bool isLocked;
        bool isOnline;
        QString liftType;
        QList<int> availableFloors;
    };
    QList<LiftData> m_liftList;
};

// 区域占用列表项
class AreaOccupancyItem {
    Q_GADGET
    Q_PROPERTY(QString areaId MEMBER m_areaId)
    Q_PROPERTY(QString mapName MEMBER m_mapName)
    Q_PROPERTY(int floor MEMBER m_floor)
    Q_PROPERTY(bool isOccupied MEMBER m_isOccupied)
    Q_PROPERTY(QString occupiedBy MEMBER m_occupiedBy)
    Q_PROPERTY(bool isThirdParty MEMBER m_isThirdParty)

public:
    QString m_areaId;
    QString m_mapName;
    int m_floor{1};
    bool m_isOccupied{false};
    QString m_occupiedBy;
    bool m_isThirdParty{false};
};

// 区域占用列表模型
class AreaOccupancyModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum AreaRoles {
        AreaIdRole = Qt::UserRole + 1,
        MapNameRole,
        FloorRole,
        IsOccupiedRole,
        OccupiedByRole,
        IsThirdPartyRole,
        OccupationStateRole
    };
    Q_ENUM(AreaRoles)

    explicit AreaOccupancyModel(QObject* parent = nullptr);
    ~AreaOccupancyModel() override = default;

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

    Q_INVOKABLE QVariantMap getAreaData(int row) const;

    void updateData(const QList<std::tuple<QString, int, std::shared_ptr<application::area::Area>>>& areas,
                   const QList<application::third_area::ThirdBlockArea*>& thirdAreas);

private:
    struct AreaData {
        QString areaId;
        QString mapName;
        int floor;
        bool isOccupied;
        QString occupiedBy;
        bool isThirdParty;
        QString occupationState;
    };
    QList<AreaData> m_areaList;
};

// 自动门列表模型
class AutoDoorListModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum AutoDoorRoles {
        DoorIdRole = Qt::UserRole + 1,
        FloorRole,
        DeviceIdRole,
        Point1Role,
        Point2Role,
        StateRole,
        IsOnlineRole
    };
    Q_ENUM(AutoDoorRoles)

    explicit AutoDoorListModel(QObject* parent = nullptr);
    ~AutoDoorListModel() override = default;

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

    Q_INVOKABLE QVariantMap getDoorData(int row) const;
    void updateData(const QList<application::auto_door::AutoDoorManager::DoorInfo>& doors);

private:
    struct AutoDoorData {
        int doorId{0};
        int floor{-1};
        quint32 deviceId{0};
        QString point1;
        QString point2;
        QString state;
        bool isOnline{false};
    };

    QList<AutoDoorData> m_doorList;
};

// 呼叫器列表模型
class CallerListModel : public QAbstractListModel {
    Q_OBJECT

public:
    enum CallerRoles {
        CallerNumRole = Qt::UserRole + 1,
        TaskNameRole,
        IsOnlineRole,
        LastTriggerRole,
        LastTriggerTextRole
    };
    Q_ENUM(CallerRoles)

    explicit CallerListModel(QObject* parent = nullptr);
    ~CallerListModel() override = default;

    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

    void updateData(const QList<application::caller::CallerRuntimeInfo>& callers);

private:
    struct CallerData {
        int callerNum{0};
        QString taskName;
        bool isOnline{false};
        QDateTime lastTriggerTime;
        QString lastTriggerText;
    };

    QList<CallerData> m_callers;
};

// 资源管理ViewModel
class ResourceViewModel : public BaseViewModel {
    Q_OBJECT
    Q_PROPERTY(LiftListModel* liftListModel READ liftListModel CONSTANT)
    Q_PROPERTY(AreaOccupancyModel* areaOccupancyModel READ areaOccupancyModel CONSTANT)
    Q_PROPERTY(AutoDoorListModel* autoDoorListModel READ autoDoorListModel CONSTANT)
    Q_PROPERTY(CallerListModel* callerListModel READ callerListModel CONSTANT)
    Q_PROPERTY(int totalLiftCount READ totalLiftCount NOTIFY totalLiftCountChanged)
    Q_PROPERTY(int totalAreaCount READ totalAreaCount NOTIFY totalAreaCountChanged)
    Q_PROPERTY(int occupiedAreaCount READ occupiedAreaCount NOTIFY occupiedAreaCountChanged)
    Q_PROPERTY(int totalAutoDoorCount READ totalAutoDoorCount NOTIFY totalAutoDoorCountChanged)
    Q_PROPERTY(int onlineAutoDoorCount READ onlineAutoDoorCount NOTIFY onlineAutoDoorCountChanged)
    Q_PROPERTY(int totalCallerCount READ totalCallerCount NOTIFY totalCallerCountChanged)
    Q_PROPERTY(int onlineCallerCount READ onlineCallerCount NOTIFY onlineCallerCountChanged)

public:
    explicit ResourceViewModel(
        std::shared_ptr<application::MapApplicationService> mapService,
        QObject* parent = nullptr
    );
    ~ResourceViewModel() override = default;

    // 属性访问器
    LiftListModel* liftListModel() { return m_liftListModel; }
    AreaOccupancyModel* areaOccupancyModel() { return m_areaOccupancyModel; }
    AutoDoorListModel* autoDoorListModel() { return m_autoDoorListModel; }
    CallerListModel* callerListModel() { return m_callerListModel; }
    int totalLiftCount() const { return m_totalLiftCount; }
    int totalAreaCount() const { return m_totalAreaCount; }
    int occupiedAreaCount() const { return m_occupiedAreaCount; }
    int totalAutoDoorCount() const { return m_totalAutoDoorCount; }
    int onlineAutoDoorCount() const { return m_onlineAutoDoorCount; }
    int totalCallerCount() const { return m_totalCallerCount; }
    int onlineCallerCount() const { return m_onlineCallerCount; }

    // 初始化
    void initialize() override;
    void cleanup() override;

    // 电梯控制
    Q_INVOKABLE bool callLift(int liftNum, int targetFloor);
    Q_INVOKABLE bool openLiftDoor(int liftNum);
    Q_INVOKABLE bool closeLiftDoor(int liftNum);
    Q_INVOKABLE bool lockLift(int liftNum);
    Q_INVOKABLE bool unlockLift(int liftNum);

    // 区域控制
    Q_INVOKABLE bool forceReleaseArea(const QString& areaId, int floor);
    Q_INVOKABLE bool forceReleaseThirdArea(const QString& areaId);

    // 自动门控制
    Q_INVOKABLE bool openAutoDoor(int doorId);
    Q_INVOKABLE bool closeAutoDoor(int doorId);

    // 刷新数据
    Q_INVOKABLE void refreshLiftData();
    Q_INVOKABLE void refreshAreaData();
    Q_INVOKABLE void refreshAutoDoorData();
    Q_INVOKABLE void refreshCallerData();
    Q_INVOKABLE void refreshAllData();

signals:
    void totalLiftCountChanged();
    void totalAreaCountChanged();
    void occupiedAreaCountChanged();
    void totalAutoDoorCountChanged();
    void onlineAutoDoorCountChanged();
    void totalCallerCountChanged();
    void onlineCallerCountChanged();
    void operationSuccess(const QString& message);
    void operationFailed(const QString& error);

private slots:
    void onRefreshTimer();
    void onLiftStatusChanged();
    void onAreaOccupancyChanged();
    void onAreaManagerSignal(const QString& areaId);
    void onThirdAreaSignal(const QString& areaId, const QString& vehicleId);
    void onAutoDoorStateChanged();

private:
    std::shared_ptr<application::auto_door::AutoDoorManager> ensureAutoDoorManager();
    void setupAutoDoorConnections();
    void updateLiftList();
    void updateAreaList();
    void updateAutoDoorList();
    void updateCallerList();
    void updateStatistics();
    void connectCallerManager(application::caller::CallerManager* manager);
    void connectAreaManager(application::area::AreaManager* manager);
    void connectThirdAreaManager(application::third_area::ThirdAreaManager* manager);

    std::shared_ptr<application::MapApplicationService> m_mapService;
    LiftListModel* m_liftListModel;
    AreaOccupancyModel* m_areaOccupancyModel;
    AutoDoorListModel* m_autoDoorListModel;
    CallerListModel* m_callerListModel;
    QTimer* m_refreshTimer;

    int m_totalLiftCount{0};
    int m_totalAreaCount{0};
    int m_occupiedAreaCount{0};
    int m_totalAutoDoorCount{0};
    int m_onlineAutoDoorCount{0};
    int m_totalCallerCount{0};
    int m_onlineCallerCount{0};

    std::shared_ptr<application::auto_door::AutoDoorManager> m_autoDoorManager;
    bool m_autoDoorSignalsConnected{false};
    QSet<application::caller::CallerManager*> m_connectedCallerManagers;
    QSet<application::area::AreaManager*> m_connectedAreaManagers;
    QSet<application::third_area::ThirdAreaManager*> m_connectedThirdAreaManagers;
};

} // namespace viewmodels
} // namespace presentation
